#include <header.h>
#include "../include/linked_list.h"

void broadcast(LinkedList* linked_users, int net_fd, char *buf, int len){
    Node *curr = linked_users->head;
    while(curr){
        if(curr->data != net_fd){
            send(curr->data, buf, len, 0);
        }
        curr = curr->next;
    }
}

void print_list(LinkedList* list){
	Node* curr = list->head;
	while (curr){
		printf("%d ", curr->data);
		curr = curr->next;
	}
	printf("\n");	
}


int main(int argc, char* argv[]){
	ARGS_CHECK(argc, 1);

	char *port = "8080";
	char *ip = "192.168.169.128";
	int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
	ERROR_CHECK(socket_fd, -1, "socket");

	// 端口复用
	int reuse = 1;
	setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse);

	// 绑定ip
	struct sockaddr_in serveraddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(atoi(port));
	serveraddr.sin_addr.s_addr = inet_addr(ip);
	int ret_bind = bind(socket_fd, (struct sockaddr*)&serveraddr, sizeof serveraddr);
	ERROR_CHECK(ret_bind, -1, "bind");
	
	// 监听
	int ret_listen = listen(socket_fd, 10);
	ERROR_CHECK(ret_listen, -1, "listen");

    // 创建一个用户链表
    LinkedList* linked_users = create_linked_list();

	int epoll_fd = epoll_create(1);

	struct epoll_event event_socket;
	event_socket.events = EPOLLIN;			/* 读取 */
	event_socket.data.fd = socket_fd;	/* 指定文件描述符 */
	epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event_socket);

	while(1){
		struct epoll_event list[8];
		int num = epoll_wait(epoll_fd, list, 8, -1);
		
		for(int i = 0; i < num; i++){
			// 有新连接
			if(list[i].data.fd == socket_fd){ 
				int net_fd = accept(socket_fd, NULL, NULL);
				ERROR_CHECK(net_fd, -1, "accept");
				// 新用户插入链表
				add_behind_tail(linked_users, net_fd);

				// 监听新用户
				struct epoll_event event_user;
				event_user.events = EPOLLIN;			/* 读取 */
				event_user.data.fd = net_fd;	/* 指定文件描述符 */
				epoll_ctl(epoll_fd, EPOLL_CTL_ADD, net_fd, &event_user);

			}else{
				// 如果不是新连接则必定是群发消息
				int net_fd = list[i].data.fd;

				char buf[1 << 10] = {0};            
				__bzero(buf, sizeof buf);
				ssize_t byte = recv(net_fd, buf, sizeof buf, 0);
				printf(buf);
				ERROR_CHECK(byte, -1, "recv");
				
				// 对方关闭，读取到0
				if(byte == 0){
					delete_node_by_data(linked_users, net_fd); 

					// epoll中要删除监听
					epoll_ctl(epoll_fd, EPOLL_CTL_DEL, net_fd, NULL);

					close(net_fd);                  
					continue;
				}

				printf("log %d:%s\n", net_fd, buf);
				// 广播,自己不发
				broadcast(linked_users, net_fd, buf, sizeof buf);
			}

		}
	}
	destroy_linked_list(linked_users);
	close(socket_fd);
	return 0;
}